# 基于pygame和matplotlib构建一个模拟简谐运动合成的程序
# 功能：能够模拟简谐运动合成的过程，并且能够通过改变参数实时发生变化
# 使用模块:pygame,pymunk,matplotlib,tkinter,numpy
# __author__ == wuJiaHao
# __version__ == 1.0
# __date__ == 2025-5-29
import sys
import pygame
from pygame import gfxdraw
import settings
import config
import math
import os
from fractions import Fraction

# 初始化窗口
pygame.init()
clock = pygame.time.Clock()
# 设置窗口大小和标题
WIDTH = 1200
HEIGHT = 600
wave_points = []
wave_points_ = []
wave_width = 600
wave_scale = 1
screen = pygame.display.set_mode((WIDTH,HEIGHT), pygame.SRCALPHA)
pygame.display.set_caption("简谐运动合成演示")

# 创建按钮类
class Button:
    def __init__(self, x, y, width, height, text, color, hover_color, callback,size = 24):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.hover_color = hover_color
        self.callback = callback
        self.hovered = False
        self.font_size = size
        if getattr(sys, 'frozen', False):
            base_path = sys._MEIPASS
        else:
            base_path = os.path.dirname(os.path.abspath(__file__))
        # 对建设路径或施工路径进行修改或调整的过程
        font_path = os.path.join(base_path, "font", "font.ttf")
        self.font = pygame.font.Font(font_path, self.font_size)  # 使用默认字体，字号36

    def draw(self, surface):
        # 根据悬停状态选择颜色
        current_color = self.hover_color if self.hovered else self.color
        pygame.draw.rect(surface, current_color, self.rect, border_radius=5)
        text_color = (207, 142, 103) if self.hovered else (80, 80, 80)
        # 渲染文字
        text_surf = self.font.render(self.text, True, text_color)
        text_rect = text_surf.get_rect(center=self.rect.center)
        surface.blit(text_surf, text_rect)

    def handle_event(self, event):
        if event.type == pygame.MOUSEMOTION:
            # 检测鼠标是否悬停在按钮上
            self.hovered = self.rect.collidepoint(event.pos)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if self.hovered and event.button == 1:  # 左键点击
                self.callback()

# 回调函数 --作用:启动设置页面
def button_click_settings():
    settings.settings()
# 在 button_pause 回调函数中添加状态标记
def button_pause():
    if config.paused:
        config.paused = False
        config.state = "run"
        button_pause.text = "暂停"
        # config.angular_speed = config.save_angular_speed
    else:
        config.paused = True
        config.state = "pause"
        button_pause.text = "运行"
        # config.save_angular_speed = config.angular_speed
        # config.angular_speed = 0

def bg_reset():
    config.angular_speed = 0.22
    config.next_angular_speed = 0.20
    config.radius = 50
    config.background_color = (217, 255, 236)
    config.ball_color = (207, 142, 103)
    config.ball_radius = 10
    config.phase = Fraction(0, 1)
    config.interval = 1
    config.theta_two = 0
    config.next_theta_two = 0
    config.angular_speed_two = 0.02
    config.next_angular_speed_two = 0.02
    config.trajectory_points = []
def ranging():
    mouse_pos = pygame.mouse.get_pos()
    for pos in config.click_pos:
        if config.click_pos[0][1]<=HEIGHT:
            pygame.draw.circle(screen, (0, 0, 255), pos, 3)
    if len(config.click_pos) >= 2 and config.click_pos[0][1]<=HEIGHT-35 and config.click_pos[1][1]<=HEIGHT-35:
        dx = config.click_pos[1][0] - config.click_pos[0][0]
        dy = config.click_pos[1][1] - config.click_pos[0][1]
        distance = math.sqrt(dx ** 2 + dy ** 2)
        font = pygame.font.SysFont("Arial", 20)
        text = font.render(f" {distance/config.Scaling:.2f}m", True, (0, 0, 0))
        screen.blit(text, (int((config.click_pos[0][0] + config.click_pos[1][0]) / 2), int((config.click_pos[0][1] + config.click_pos[1][1]) / 2)))
        pygame.draw.aaline(screen, (0, 0, 255), config.click_pos[0], config.click_pos[1], 1)
    pygame.draw.circle(screen, config.object_color, mouse_pos, 2)
def page1():
    config.page1_started = True
    config.page2_started = False
    config.page3_started = False
    # button_page1.color = "#80ffff"
    # button_page1.hover_color = "#80ffff"
    # button_page2.color = config.background_color
    # button_page2.hover_color = config.background_color
    # button_page3.color = config.background_color
    # button_page3.hover_color = config.background_color
def page2():
    config.page2_started = True
    config.page1_started = False
    config.page3_started = False
    # 新增初始化相位差参数
    if not hasattr(config, 'initial_phase_diff'):
        config.initial_phase_diff = math.pi / 2  # 初始相位差（可调整）
    button_page2.color = "#80ffff"
    button_page2.hover_color = "#80ffff"
    button_page1.color = config.background_color
    button_page1.hover_color = config.background_color
    button_page3.color = config.background_color
    button_page3.hover_color = config.background_color
def page3():
    config.page3_started = True
    config.page1_started = False
    config.page2_started = False
    button_page3.color = "#80ffff"
    button_page3.hover_color = "#80ffff"
    button_page1.color = config.background_color
    button_page1.hover_color = config.background_color
    button_page2.color = config.background_color
    button_page2.hover_color = config.background_color
def phase_plus():
    config.theta_two += math.pi*(1/config.interval)
    config.phase += Fraction(1,config.interval)
def phase_minus():
    config.theta_two -= math.pi*(1/config.interval)
    config.phase -= Fraction(1,config.interval)
# 创建按钮实例
button_settings = Button(
    x=WIDTH-100, y=HEIGHT-35,
    width=100, height=30,
    text="设置",
    color=(191, 236, 242),
    hover_color=(191, 236, 255),
    callback=button_click_settings
)
button_angular_speed_plus = Button(
    x=175, y=HEIGHT-145,
    width=10, height=20,
    text="+",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"angular_speed",config.angular_speed+0.01)
)
button_angular_speed_minus = Button(
    x=190, y=HEIGHT-145,
    width=10, height=20,
    text="-",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"angular_speed",config.angular_speed-0.01)
)
button_next_angular_speed_plus = Button(
    x=175, y=HEIGHT-115,
    width=10, height=20,
    text="+",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"next_angular_speed",config.next_angular_speed+0.01)
)
button_next_angular_speed_minus = Button(
    x=190, y=HEIGHT-115,
    width=10, height=20,
    text="-",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"next_angular_speed",config.next_angular_speed-0.01)
)
button_trajectory_radius_plus = Button(
    x=160, y=HEIGHT-80,
    width=10, height=20,
    text="+",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"radius",config.radius+5)
)
button_trajectory_radius_minus = Button(
    x=175, y=HEIGHT-80,
    width=10, height=20,
    text="-",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"radius",config.radius-5)
)
button_pause = Button(
    x=WIDTH-320, y=HEIGHT-35,
    width=90, height=30,
    text="运行",
    color=config.background_color,
    hover_color=config.background_color,
    callback=button_pause
)
button_bg_reset = Button(
    x=WIDTH-210, y=HEIGHT-35,
    width=80, height=30,
    text="重置",
    color=config.background_color,
    hover_color=config.background_color,
    callback=bg_reset
)
button_ranging = Button(
    x=WIDTH-440, y=HEIGHT-35,
    width=80, height=30,
    text="测量",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"ranging",not config.ranging)
)
button_page1 = Button(
    x=WIDTH-105, y=HEIGHT-130,
    width=120, height=30,
    text="同方向同频率",
    color=config.background_color,
    hover_color=config.background_color,
    callback=page1,
    size=18
)
button_page2 = Button(
    x=WIDTH-105, y=HEIGHT-100,
    width=120, height=30,
    text="不同方向",
    color=config.background_color,
    hover_color=config.background_color,
    callback=page2,
    size=18
)
button_page3 = Button(
    x=WIDTH-105, y=HEIGHT-70,
    width=120, height=30,
    text="同方向同频率",
    color=config.background_color,
    hover_color=config.background_color,
    callback=page3,
    size=18
)
button_phase_plus = Button(
    x=WIDTH-140, y=20,
    width=20, height=30,
    text="+",
    color=config.background_color,
    hover_color=config.background_color,
    callback=phase_plus
)
button_phase_minus = Button(
    x=WIDTH-115, y=20,
    width=20, height=30,
    text="-",
    color=config.background_color,
    hover_color=config.background_color,
    callback=phase_minus
)
button_interval_plus = Button(
    x=WIDTH-140, y=55,
    width=20, height=30,
    text="+",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"interval",config.interval+1)
)
button_interval_minus = Button(
    x=WIDTH-115, y=55,
    width=20, height=30,
    text="-",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"interval",config.interval-1)
)
button_angular_speed_two_plus = Button(
    x=175, y=500,
    width=10, height=20,
    text="+",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"angular_speed_two",config.angular_speed_two+0.005)
)
button_angular_speed_two_minus = Button(
    x=190, y=500,
    width=10, height=20,
    text="-",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"angular_speed_two",config.angular_speed_two-0.005)
)
button_next_angular_speed_two_plus = Button(
    x=175, y=522,
    width=10, height=20,
    text="+",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"next_angular_speed_two",config.next_angular_speed_two+0.005)
)
button_next_angular_speed_two_minus = Button(
    x=190, y=522,
    width=10, height=20,
    text="-",
    color=config.background_color,
    hover_color=config.background_color,
    callback=lambda:setattr(config,"next_angular_speed_two",config.next_angular_speed_two-0.005)
)
def draw_text(text,size,color,x,y,):
    # 获取开发版本和打包版本的字体路径
    if getattr(sys, 'frozen', False):
        base_path = sys._MEIPASS
    else:
        base_path = os.path.dirname(os.path.abspath(__file__))
    # 对建设路径或施工路径进行修改或调整的过程
    font_path = os.path.join(base_path, "font", "font.ttf")
    font = pygame.font.Font(font_path, size)
    text = font.render(text, True, color)
    screen.blit(text, (x, y))

def draw_text_normal(text,size,color,x,y,):
    # 加载字体文件
    font = pygame.font.SysFont("Arial", size)
    # 设置字体参数
    text = font.render(text, True, color)
    # 文本绘制在屏幕上
    screen.blit(text, (x, y))

def main():
    """
    主函数，用于初始化pygame和matplotlib，创建窗口和画布，启动事件循环。
    """
    # pygame事件循环

    while True:
        # 设置窗口背景颜色为白色
        screen.fill(config.background_color)


        # 动态更新按钮颜色
        button_pause.color = config.background_color
        button_pause.hover_color = config.background_color
        button_bg_reset.color = config.background_color
        button_bg_reset.hover_color = config.background_color
        button_ranging.color = config.background_color
        button_ranging.hover_color = config.background_color
        mouse_pos = pygame.mouse.get_pos()
        if config.bg_refresh:
            config.bg_refresh = False
            bg_reset()
            break
        if config.ranging:
            ranging()
            button_ranging.text = "取消"
            config.model = "measuring"
        else:
            button_ranging.text = "测量"
            config.model = None
            config.click_pos = []
        # 绘制鼠标位置
        mouse_pos = pygame.mouse.get_pos()
        # 绘制文本

        if config.page1_started:
            draw_text("简谐运动的合成(同方向)", 26, (0,0,0), (WIDTH - 260) // 2, 20)
            draw_text(f"角频率：{config.angular_speed*config.speed_Scaling:.1f}rad/s",18,config.font_color,10,HEIGHT-140)
            draw_text(f"角频率：{config.next_angular_speed*config.speed_Scaling:.1f}rad/s",18,config.font_color,10,HEIGHT-110)
            draw_text(f"轨迹半径：{config.radius/config.Scaling}m",18,config.font_color,10,HEIGHT-80)
            button_angular_speed_plus.draw(screen)
            button_angular_speed_plus.color = config.background_color
            button_angular_speed_plus.hover_color = config.background_color
            button_angular_speed_minus.draw(screen)
            button_angular_speed_minus.color = config.background_color
            button_angular_speed_minus.hover_color = config.background_color

            button_trajectory_radius_plus.draw(screen)
            button_trajectory_radius_plus.color = config.background_color
            button_trajectory_radius_plus.hover_color = config.background_color
            button_trajectory_radius_minus.draw(screen)
            button_trajectory_radius_minus.color = config.background_color
            button_trajectory_radius_minus.hover_color = config.background_color


            button_next_angular_speed_plus.draw(screen)
            button_next_angular_speed_plus.color = config.background_color
            button_next_angular_speed_plus.hover_color = config.background_color
            button_next_angular_speed_minus.draw(screen)
            button_next_angular_speed_minus.color = config.background_color
            button_next_angular_speed_minus.hover_color = config.background_color


        if config.page2_started:
            draw_text("简谐运动的合成(不同方向)", 26, (0, 0, 0), (WIDTH - 360) // 2, 20)
            # 添加频率相等判断条件
            if math.isclose(config.angular_speed_two, config.next_angular_speed_two, abs_tol=0.001):
                config.oprate_time += 1
                button_phase_plus.draw(screen)
                button_phase_minus.draw(screen)
                button_interval_plus.draw(screen)
                button_interval_minus.draw(screen)
                draw_text(f"间隔:π/{config.interval}", 20, (0, 0, 0), WIDTH - 250, 60)

            # 保留其他按钮绘制
            button_angular_speed_two_plus.draw(screen)
            button_angular_speed_two_minus.draw(screen)
            button_next_angular_speed_two_plus.draw(screen)
            button_next_angular_speed_two_minus.draw(screen)

        draw_text(f"Mouse position:({mouse_pos[0]-config.center[0]},{-(mouse_pos[1]-config.center[1])})",20,(80,80,80),10,HEIGHT-30)
        draw_text(f"Fps:{int(clock.get_fps())}",20,(80,80,80),220,HEIGHT-30)
        draw_text(f"State:{config.state}",20,(80,80,80),290,HEIGHT-30)
        draw_text(f"Model:{config.model}",20,(80,80,80),390,HEIGHT-30)
        # 在事件处理循环中添加页面状态判断
        for event in pygame.event.get():
            if config.ranging:
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if len(config.click_pos) >= 2:
                        config.click_pos = []
                    config.click_pos.append(mouse_pos)
            if event.type == pygame.QUIT:
                pygame.quit()
                return

            # 修改以下部分：根据当前页面控制按钮响应
            if config.page1_started:
                button_angular_speed_plus.handle_event(event)
                button_angular_speed_minus.handle_event(event)
                button_trajectory_radius_plus.handle_event(event)
                button_trajectory_radius_minus.handle_event(event)
                button_next_angular_speed_plus.handle_event(event)
                button_next_angular_speed_minus.handle_event(event)

            if config.page2_started:
                button_angular_speed_two_plus.handle_event(event)
                button_angular_speed_two_minus.handle_event(event)
                button_next_angular_speed_two_plus.handle_event(event)
                button_next_angular_speed_two_minus.handle_event(event)
                button_phase_plus.handle_event(event)
                button_phase_minus.handle_event(event)
                button_interval_plus.handle_event(event)
                button_interval_minus.handle_event(event)

            # 这些是全局按钮，始终响应
            button_settings.handle_event(event)
            button_pause.handle_event(event)
            button_bg_reset.handle_event(event)
            button_ranging.handle_event(event)
            button_page1.handle_event(event)
            button_page2.handle_event(event)
            button_page3.handle_event(event)
            # 绘制按钮
            button_next_angular_speed_minus.handle_event(event)
            button_next_angular_speed_plus.handle_event(event)
            button_phase_plus.handle_event(event)
            button_phase_minus.handle_event(event)
            button_interval_plus.handle_event(event)
            button_interval_minus.handle_event(event)
            button_angular_speed_two_plus.handle_event(event)
            button_angular_speed_two_minus.handle_event(event)
            button_next_angular_speed_two_plus.handle_event(event)
            button_next_angular_speed_two_minus.handle_event(event)
        button_settings.draw(screen)
        button_pause.draw(screen)
        button_bg_reset.draw(screen)
        button_ranging.draw(screen)
        button_page1.draw(screen)
        button_page2.draw(screen)
        button_page3.draw(screen)
        # 坐标系绘制
        # 第一个页面的内容
        if config.page1_started:
            button_page1.color = "#80ffff"
            button_page1.hover_color = "#80ffff"
            button_page2.color = config.background_color
            button_page2.hover_color = config.background_color
            button_page3.color = config.background_color
            button_page3.hover_color = config.background_color
            pygame.draw.line(screen,config.reference_color,(0,config.center[1]),(WIDTH,config.center[1]))
            pygame.draw.line(screen,config.reference_color,(config.center[0],0),(config.center[0],HEIGHT-40))
            # 绘制坐标系刻度
            for i in range(-WIDTH,WIDTH,20):
                pygame.draw.line(screen,config.reference_color,(config.center[0]+i,config.center[1]-2),(config.center[0]+i,config.center[1]+2))
            for i in range(-HEIGHT//2+45,HEIGHT,20):
                pygame.draw.line(screen,config.reference_color,(config.center[0]-2,config.center[1]-i),(config.center[0]+2,config.center[1]-i))

            # 角度计算（仅在非暂停状态更新）
            if not config.paused:
                config.theta += config.angular_speed
                config.next_theta += config.next_angular_speed
            # 小球坐标计算
            # 第一个小球的坐标
            x = config.center[0]+config.radius*math.cos(config.theta)
            y = config.center[1]-config.radius*math.sin(config.theta)
            # 第二个小球的坐标
            x_next = config.center[0] + config.radius * math.cos(config.next_theta+math.pi/2)
            y_next = config.center[1] - config.radius * math.sin(config.next_theta+math.pi/2)
            # 合成之后的小球坐标
            x0 = x+x_next-config.center[0]
            y0 = y+y_next-config.center[1]
        # 绘制的小球与坐标原点的连接线
            pygame.draw.aaline(screen,(0,0,255),config.center,(int(x),int(y)))
            pygame.draw.aaline(screen,(0,0,255),config.center,(int(x_next),int(y_next)))
            pygame.draw.aaline(screen,(0,0,255),config.center,(int(x0),int(y0)))

        # 波形图更新（仅在非暂停状态更新）
            if not config.paused:
                wave_points.append(y0)
                if len(wave_points) > 500:
                    wave_points.pop(0)
            # draw_text_normal(f"({(int(x0)-200)/config.Scaling}m,{-(int(y0)-300)/config.Scaling}m)",18,(0,0,0),x0+10,y0+10)
            if len(wave_points) > 1:
                points = []
                for i, y_val in enumerate(wave_points):
                    # 将历史数据映射到右侧波形区
                    x_wave = 600 + (i * wave_width / 500)
                    y_wave = (y_val - config.center[1]) * wave_scale + config.center[1]
                    points.append((x_wave, y_wave))
                # 绘制波形曲线（始终绘制历史数据）
                pygame.draw.aalines(screen, (31, 119, 180), False, points, 2)
            if len(wave_points) > 0:
                # 仅在非暂停状态绘制连接线和波形点
                if not config.paused:
                    current_index = len(wave_points) - 1
                    wave_x = 600 + current_index * (wave_width / 500)
                    wave_y = (y0 - config.center[1]) * wave_scale + config.center[1]
                    # 绘制连接线（分两段保持水平）
                    pygame.draw.line(screen, "#00ff00", (x0, y0), (600, y0), 2)
                    pygame.draw.line(screen, "#00ff00", (600, wave_y), (wave_x, wave_y), 2)
                    pygame.draw.circle(screen, "#00ff00", (int(wave_x), int(wave_y)), 5)
            # 绘制轨迹
            # pygame.draw.circle(screen, (0,0,0), config.center, config.radius, 1)
            pygame.gfxdraw.aacircle(screen,config.center[0],config.center[1],config.radius,(0,0,0))
            # pygame.gfxdraw.aacircle(screen,config.center[0],config.center[1],config.next_radius,(0,0,0))
            # 绘制小球
            pygame.draw.circle(screen,config.object_color,(int(x),int(y)),8)
            pygame.draw.circle(screen,config.object_color,(int(x_next),int(y_next)),8)
        # 合成之后的小球
            pygame.draw.circle(screen,config.object_color,(int(x0),int(y0)),8)
        # 第二个页面的内容
        if config.page2_started:

            if not config.paused:
                config.theta_two += config.angular_speed_two
                config.next_theta_two += config.next_angular_speed_two
            pygame.draw.line(screen, config.reference_color, (0, config.center[1]), (WIDTH, config.center[1]))
            pygame.draw.line(screen, config.reference_color, (config.center[0], 0), (config.center[0], HEIGHT - 40))
            # 第一个小球坐标
            x1 = config.center_one[0] + config.radius_two * math.cos(config.theta_two)
            y1 = config.center_one[1] - config.radius_two * math.sin(config.theta_two)
            # 第二个小球坐标
            x2 = config.center_two[0] + config.next_radius_two * math.cos(config.next_theta_two)
            y2 = config.center_two[1] - config.next_radius_two * math.sin(config.next_theta_two)
            # 绘制的小球与坐标原点的连接线
            pygame.draw.aaline(screen, (0, 0, 255), config.center_one, (int(x1), int(y1)))
            pygame.draw.aaline(screen, (0, 0, 255), config.center_two, (int(x2), int(y2)))
            # 第一个小球
            pygame.draw.circle(screen,config.object_color,(int(x1),int(y1)),8)
            # 第一个小球的名字
            # draw_text("球1",18,(0,0,0),x1+10,y1+10)
            # 第一个小球的轨迹
            pygame.gfxdraw.aacircle(screen,config.center_one[0],config.center_one[1],config.radius_two,(0,0,0))
            # 第二个小球
            pygame.draw.circle(screen, config.object_color, (int(x2), int(y2)), 8)
            # 第二个小球的名字
            # draw_text("球2", 18, (0, 0, 0), x2 + 10, y2 + 10)
            # 第二个小球的轨迹
            pygame.gfxdraw.aacircle(screen, config.center_two[0], config.center_two[1], config.radius_two, (0, 0, 0))
            # 合成之后的小球
            x0 = x1
            y0 = y2
            pygame.draw.circle(screen, (0,0,255), (int(x0), int(y0)), 4)

            # 新增轨迹绘制逻辑
            if not config.paused:
                config.trajectory_points.append((x0, y0))
                if len(config.trajectory_points) > config.points_two_len:
                    config.trajectory_points.pop(0)

            # 绘制历史轨迹点
            for point in config.trajectory_points:

                pygame.draw.circle(screen, (255, 0, 0), (int(point[0]), int(point[1])), 1)

            if config.phase.denominator == 1:
                nums = str(config.phase.numerator)+"π"
            elif config.phase.numerator == 1:
                nums = "π/"+str(config.phase.denominator)
            else:
                nums = f"{config.phase.numerator}π/{config.phase.denominator}"
            if config.interval <= 0:
                config.interval = 1
            if config.angular_speed_two  == config.next_angular_speed_two:
                if config.oprate_time == 0:
                    draw_text(f"相位差:{nums}", 20, (0, 0, 0),WIDTH-280,25)
                else:
                    draw_text(f"相位差:{(config.theta_two-config.next_theta_two)%2*math.pi:.2f}", 20, (0, 0, 0),WIDTH-280,25)
            else:
                draw_text(f"相位差:{(config.theta_two-config.next_theta_two)%2*math.pi:.2f}", 20, (0, 0, 0),WIDTH-280,25)
            draw_text(f"角频率w1：{config.angular_speed_two*config.speed_Scaling:.1f}rad/s", 18, (0, 0, 0), 10, 500)
            draw_text(f"角频率w2：{config.next_angular_speed_two*config.speed_Scaling:.1f}rad/s", 18, (0, 0, 0), 10, 525)
            pygame.draw.aaline(screen, (0, 255, 0), (x1, y1), (x0, y0), 2)
            pygame.draw.aaline(screen, (0, 255, 0), (x2, y2), (x0, y0), 2)
        if config.page3_started:

            draw_text("简谐运动的合成(同方向同频率)", 26, (0, 0, 0), (WIDTH - 360) // 2, 20)
            button_page1.color = config.background_color
            button_page1.hover_color = config.background_color
            button_page2.color = config.background_color
            button_page2.color = config.background_color
            button_page2.hover_color = config.background_color
            button_page3.color = "#80ffff"
            button_page3.hover_color = "#80ffff"
            pygame.draw.line(screen, config.reference_color, (0, config.center[1]), (WIDTH, config.center[1]))
            pygame.draw.line(screen, config.reference_color, (config.center[0], 0), (config.center[0], HEIGHT - 40))
            # 绘制坐标系刻度
            for i in range(-WIDTH, WIDTH, 20):
                pygame.draw.line(screen, config.reference_color, (config.center[0] + i, config.center[1] - 2),
                                 (config.center[0] + i, config.center[1] + 2))
            for i in range(-HEIGHT // 2 + 45, HEIGHT, 20):
                pygame.draw.line(screen, config.reference_color, (config.center[0] - 2, config.center[1] - i),
                                 (config.center[0] + 2, config.center[1] - i))

            # 角度计算（仅在非暂停状态更新）
            if not config.paused:
                config.theta_ += 0.1
                config.next_theta_ += 0.1
            # 小球坐标计算
            # 第一个小球的坐标
            x = config.center[0] + config.radius * math.cos(config.theta_)
            y = config.center[1] - config.radius * math.sin(config.theta_)
            # 第二个小球的坐标
            x_next = config.center[0] + config.radius * math.cos(config.next_theta_ + math.pi / 2)
            y_next = config.center[1] - config.radius * math.sin(config.next_theta_ + math.pi / 2)
            # 合成之后的小球坐标
            x0 = x + x_next - config.center[0]
            y0 = y + y_next - config.center[1]
            # 绘制的小球与坐标原点的连接线
            pygame.draw.aaline(screen, (0, 0, 255), config.center, (int(x), int(y)))
            pygame.draw.aaline(screen, (0, 0, 255), config.center, (int(x_next), int(y_next)))
            pygame.draw.aaline(screen, (0, 0, 255), config.center, (int(x0), int(y0)))

            # 波形图更新（仅在非暂停状态更新）
            if not config.paused:
                wave_points_.append(y0)
                if len(wave_points_) > 500:
                    wave_points_.pop(0)
            if len(wave_points_) > 1:
                points_ = []
                for i, y_val in enumerate(wave_points_):
                    # 将历史数据映射到右侧波形区
                    x_wave = 600 + (i * wave_width / 500)
                    y_wave = (y_val - config.center[1]) * wave_scale + config.center[1]
                    points_.append((x_wave, y_wave))
                # 绘制波形曲线（始终绘制历史数据）
                pygame.draw.aalines(screen, (31, 119, 180), False, points_, 2)
            if len(wave_points_) > 0:
                # 仅在非暂停状态绘制连接线和波形点
                if not config.paused:
                    current_index = len(wave_points_) - 1
                    wave_x = 600 + current_index * (wave_width / 500)
                    wave_y = (y0 - config.center[1]) * wave_scale + config.center[1]
                    # 绘制连接线（分两段保持水平）
                    pygame.draw.line(screen, "#00ff00", (x0, y0), (600, y0), 2)
                    pygame.draw.line(screen, "#00ff00", (600, wave_y), (wave_x, wave_y), 2)
                    pygame.draw.circle(screen, "#00ff00", (int(wave_x), int(wave_y)), 5)
            # 绘制轨迹
            # pygame.draw.circle(screen, (0,0,0), config.center, config.radius, 1)
            pygame.gfxdraw.aacircle(screen, config.center[0], config.center[1], config.radius, (0, 0, 0))
            # pygame.gfxdraw.aacircle(screen,config.center[0],config.center[1],config.next_radius,(0,0,0))
            # 绘制小球
            pygame.draw.circle(screen, config.object_color, (int(x), int(y)), 8)
            pygame.draw.circle(screen, config.object_color, (int(x_next), int(y_next)), 8)
            # 合成之后的小球
            pygame.draw.circle(screen, config.object_color, (int(x0), int(y0)), 8)
        # 页面下方工具栏的范围线
        pygame.draw.line(screen, (0, 0, 0), (0, HEIGHT - 40), (WIDTH, HEIGHT - 40))
        pygame.display.update()
        clock.tick(60)

if __name__ == "__main__":
    main()